package com.qdlc.p2p.dal.dao.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.persistence.Query;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Repository;

import com.google.common.base.Joiner;
import com.qdlc.p2p.common.constant.Global;
import com.qdlc.p2p.common.constant.RedEnvelopeType;
import com.qdlc.p2p.common.constant.RedStatus;
import com.qdlc.p2p.common.util.DateUtil;
import com.qdlc.p2p.common.util.NumberUtil;
import com.qdlc.p2p.dal.common.dao.jpa.BaseDaoImpl;
import com.qdlc.p2p.dal.common.model.jpa.PageDataList;
import com.qdlc.p2p.dal.common.model.jpa.QueryParam;
import com.qdlc.p2p.dal.dao.UserRedEnvelopeDao;
import com.qdlc.p2p.dal.dto.BondTender;
import com.qdlc.p2p.dal.dto.BorrowTender;
import com.qdlc.p2p.dal.dto.User;
import com.qdlc.p2p.dal.dto.UserRedEnvelope;
import com.qdlc.p2p.dal.model.UserRedEnvelopeModel;
import com.qdlc.p2p.dal.mybatis.model.mapper.UserRedEnvelopeMapper;
import com.qdlc.p2p.dal.mybatis.pager.PageProxyBuilder;
import com.qdlc.p2p.dal.mybatis.pager.core.PageParameter;

/**
 * 用户红包获取记录DAO接口
 *
 * @author ylx
 * @version 2.0
 * @since 2015年04月22日 13时53分30秒
 */
@Repository(value = "userRedEnvelopeDao")
public class UserRedEnvelopeDaoImpl extends BaseDaoImpl<UserRedEnvelope> implements UserRedEnvelopeDao {

	@Resource
	UserRedEnvelopeMapper userRedEnvelopeMapper;

    @Override
    public UserRedEnvelope getUserRedEnvelopeById(long id) {
        UserRedEnvelope redEnvelope = userRedEnvelopeMapper.getUserRedEnvelopeById(id);
        return redEnvelope;
    }

    @Override
    public void doInvalid(long id) {
        userRedEnvelopeMapper.changeStatusById(id, RedStatus.INVALID);
    }

    @Override
    public PageDataList<UserRedEnvelopeModel> list(UserRedEnvelopeModel model) {
    	String searchName = model.getSearchName();
    	PageProxyBuilder<UserRedEnvelopeMapper> proxyBuilder = PageProxyBuilder.newBuilder(UserRedEnvelopeMapper.class).setPageParameter(model.getPage(), model.getRows());
    	List<UserRedEnvelopeModel> list;
    	if(StringUtils.isNotBlank(searchName)){
        	list = proxyBuilder.createProxy().listByUserName(searchName);
        }else{
        	list = proxyBuilder.createProxy().list(model);
        }
    	PageParameter pageParameter = proxyBuilder.getPageParameter();
    	PageDataList<UserRedEnvelopeModel> pageDataList = new PageDataList<UserRedEnvelopeModel>(pageParameter.convert2Page(), list);
    	return pageDataList;
    }

    @Override
    public List<UserRedEnvelope> useableList(long userId) {
        List<UserRedEnvelope> list = userRedEnvelopeMapper.useableList(userId);
        return list;
    }

    @Override
    public List<UserRedEnvelope> notAvailableList(long userId) {
        List<UserRedEnvelope> list = userRedEnvelopeMapper.notAvailableList(userId);
        return list;
    }

    @Override
    public double getTotalAmountByIds(long[] redEnvelopeIds, long toUserId) {
        if (redEnvelopeIds == null) {
            return 0;
        }
        Double totalPacketMoney = userRedEnvelopeMapper.getTotalAmountByIds(redEnvelopeIds, toUserId);
        if(totalPacketMoney == null){
        	totalPacketMoney = 0.0D;
        }
        return totalPacketMoney;
    }

    @Override
    public double getTenderUseAmount(long tenderId) {
        Double amount = userRedEnvelopeMapper.getTotalAmountByKeyIdAndUseType(tenderId, UserRedEnvelopeModel.USE_BORROW_TENDER);
        if(amount == null){
        	amount = 0.0D;
        }
        return amount;
    }


    @SuppressWarnings("rawtypes")
    @Override
    public double getUseRedEnvelopeSumByStatus(int status, String date) {
        String jql = "SELECT IFNULL(SUM(amount), 0) FROM " + Global.DB_PREFIX + "additional_user_red_envelope where `status` = ?1 AND date_format(use_time,'%Y-%m') = ?2";
        Query query = em.createNativeQuery(jql).setParameter(1, status).setParameter(2, date);
        double amount = 0;
        List list = query.getResultList();
        if (list != null && list.size() > 0) {
            amount = NumberUtil.getDouble(list.get(0).toString());
        }
        return amount;
    }

    @Override
    public void tenderBorrowFreezeRedEnvelope(BorrowTender borrowTender, long[] redEnvelopeIds) {
        if (redEnvelopeIds == null || redEnvelopeIds.length == 0) {
            return;
        }
        userRedEnvelopeMapper.updateKeyId(redEnvelopeIds, RedStatus.FREEZE, borrowTender.getId(), UserRedEnvelopeModel.USE_BORROW_TENDER);
    }

    @Override
    public void tenderBorrowUseRedEnvelope(long tenderId) {
    	userRedEnvelopeMapper.updateStatusByKeyIdAndUseType(RedStatus.USE, tenderId, UserRedEnvelopeModel.USE_BORROW_TENDER);
    }

    @Override
    public void tenderBorrowFailUseRedEnvelope(BorrowTender borrowTender) {
        QueryParam param = QueryParam.getInstance()
                .addParam("useType", UserRedEnvelopeModel.USE_BORROW_TENDER)
                .addParam("keyId", borrowTender.getId());
        List<UserRedEnvelope> list = this.findByCriteria(param);
        for (int i = 0; i < list.size(); i++) {
            UserRedEnvelope userRedEnvelope = list.get(i);
            // 根据使用时间与当前时间对比，将有效期时间延长，防止红包还原后已过期
            int day = DateUtil.daysBetween(DateUtil.getNow(), userRedEnvelope.getUseTime());
            int validDay = userRedEnvelope.getValidDay() + day;
            userRedEnvelope.setValidDay(validDay);
            userRedEnvelope.setExpiredTime(DateUtil.rollDay(userRedEnvelope.getAddTime(), validDay));
            userRedEnvelope.setStatus(RedStatus.NO_USE);
            userRedEnvelope.setUseType(null);
            userRedEnvelope.setKeyId(0);
            this.update(userRedEnvelope);
        }
    }

    @Override
    public double getTotalAmountByUseTypeANdKeyId(String useType, long keyId) {
        Double amount = userRedEnvelopeMapper.getTotalAmountByKeyIdAndUseType(keyId, useType);
        return amount == null ? 0.0D : amount;
    }

    @Override
    public void tenderBondUseRedEnvelope(BondTender bondTender, long[] redEnvelopeIds) {
        if (redEnvelopeIds == null || redEnvelopeIds.length == 0) {
            return;
        }
        userRedEnvelopeMapper.updateKeyId(redEnvelopeIds, RedStatus.USE, bondTender.getId(), UserRedEnvelopeModel.USE_BOND_TENDER);
    }

    @Override
    public void tenderBondFailUseRedEnvelope(BondTender bondTender) {
        QueryParam param = QueryParam.getInstance()
                .addParam("useType", UserRedEnvelopeModel.USE_BOND_TENDER)
                .addParam("keyId", bondTender.getId());
        List<UserRedEnvelope> list = this.findByCriteria(param);
        for (int i = 0; i < list.size(); i++) {
            UserRedEnvelope userRedEnvelope = list.get(i);
            // 根据使用时间与当前时间对比，将有效期时间延长，防止红包还原后已过期
            int day = DateUtil.daysBetween(DateUtil.getNow(), userRedEnvelope.getUseTime());
            int validDay = userRedEnvelope.getValidDay() + day;
            userRedEnvelope.setValidDay(validDay);
            userRedEnvelope.setExpiredTime(DateUtil.rollDay(userRedEnvelope.getAddTime(), validDay));
            userRedEnvelope.setStatus(RedStatus.NO_USE);
            userRedEnvelope.setUseType(null);
            userRedEnvelope.setKeyId(0);
            this.update(userRedEnvelope);
        }
    }

    @Override
    public double getUserRedPacketFeeByDate(String date) {
        // 只有红包使用以后才能记作为平台的支出，所以只需统计已使用的红包
        String sql = "select sum(amount) from " + Global.DB_PREFIX + "additional_user_red_envelope where date_format(use_time,'%Y-%m')=? ";
        Query query = em.createNativeQuery(sql).setParameter(1, date);
        Object obj = query.getSingleResult();
        double result = 0;
        if (obj != null) {
            result = Double.parseDouble(obj + "");
        }
        return result;
    }

    @Override
    public int userableCount(long userId) {
        int count = userRedEnvelopeMapper.checkCanUseRedEnvelope(new long[]{}, userId, UserRedEnvelopeModel.USER_RED_ENVELOPE_TYPE_VIRTUAL);
        return count;
    }

    @Override
    public boolean checkCanUseRedEnvelope(long[] redEnvelopeIds, long userId, byte redType) {
        if (redEnvelopeIds == null) {
            return false;
        }
        int count = userRedEnvelopeMapper.checkCanUseRedEnvelope(redEnvelopeIds, userId, redType);
        // 如果查询结果集个数不等于用户所选择的红包ID个数，则代表用户存在恶意修改表单提交ID的嫌疑，所以需要进行处理
        if (count == redEnvelopeIds.length) {
            return true;
        }
        return false;
    }

    @Override
    public boolean checkIsCashRedEnvelope(long[] redEnvelopeIds, User toUser) {
        if (redEnvelopeIds == null) {
            return false;
        }
        String sql = "select count(*) from " + Global.DB_PREFIX + "additional_user_red_envelope where status=:status and expired_time>:expiredTime and type=:type and user_id=:userId and id in (:ids)";
        String expiredTime = DateUtil.dateStr4(DateUtil.getNow());
        long userId = toUser.getUserId();
        List<Long> ids = new ArrayList<Long>(redEnvelopeIds.length);
        for (int i = 0; i < redEnvelopeIds.length; i++) {
            ids.add(redEnvelopeIds[i]);
        }
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("status", RedStatus.NO_USE);
        params.put("type", RedEnvelopeType.CASH);
        params.put("expiredTime", expiredTime);
        params.put("userId", userId);
        params.put("ids", Joiner.on(",").skipNulls().join(ids));
        Object result = getSingleResult(sql, params);
        int count = 0;
        if (result != null) {
            count = NumberUtil.getInt(result.toString());
        }

        // 如果查询结果集个数不等于用户所选择的红包ID个数，则代表用户存在恶意修改表单提交ID的嫌疑，所以需要进行处理
        if (count == redEnvelopeIds.length) {
            return true;
        }
        return false;
    }

    @Override
    public boolean checkIsOverdueEnvelope(long[] redEnvelopeIds, User toUser) {
        if (redEnvelopeIds == null) {
            return false;
        }
        StringBuffer sb = new StringBuffer("select count(*) from " + Global.DB_PREFIX + "additional_user_red_envelope where status = "
                + RedStatus.NO_USE + " and expired_time > '"
                + DateUtil.dateStr4(DateUtil.getNow()) + "' and type = " + RedEnvelopeType.VIRTUAL
                + " and user_id = " + toUser.getUserId() + " and id in (");
        for (int i = 0; i < redEnvelopeIds.length; i++) {
            sb.append("?,");
        }
        Query query = em.createNativeQuery(sb.substring(0, sb.length() - 1) + ")");
        for (int i = 0; i < redEnvelopeIds.length; i++) {
            query.setParameter(i + 1, redEnvelopeIds[i]);
        }
        Object result = query.getSingleResult();
        int count = 0;
        if (result != null) {
            count = NumberUtil.getInt(result.toString());
        }

        // 如果查询结果集个数不等于用户所选择的红包ID个数，则代表用户存在恶意修改表单提交ID的嫌疑，所以需要进行处理
        if (count == redEnvelopeIds.length) {
            return true;
        }
        return false;
    }

    @Override
    public int doUse(List<Long> ids, String useType, byte preStatus, Long keyId) {
        if(ids == null || ids.size() == 0) return 0;

        StringBuffer sb = new StringBuffer(UPDATE);
        sb.append(Global.DB_PREFIX).append("additional_user_red_envelope");
        sb.append(SET);
        sb.append("status = :status").append(",");
        sb.append("use_time = now()").append(",");
        sb.append("use_type = :useType");
        if(keyId != null) {
            sb.append(",key_id = :keyId");
        }
        sb.append(WHERE);
        sb.append(" id in(:ids) ").append(AND);
        sb.append(" status = :preStatus ").append(AND);
        sb.append(" use_time IS NULL ");

        // 参数设定
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("status", RedStatus.USE);
        params.put("useType", useType);
        if(keyId != null) {
            params.put("keyId", keyId);
        }
        params.put("ids", Joiner.on(",").skipNulls().join(ids));
        params.put("preStatus", preStatus);

        Query query = em.createNativeQuery(sb.toString());
        setParameter(query, params);
        return query.executeUpdate();
    }

    @Override
    public int changeStatus(long[] redEnvelopeIds, int preStatus, int aftStatus) {
        if (redEnvelopeIds == null) {
            return 0;
        }
        int count = userRedEnvelopeMapper.changeStatus(redEnvelopeIds, aftStatus, preStatus, null);
        return count;
    }

    @Override
    public void redEnvelopeExpireDispose() {
        // 将未使用且过期时间小于当前时间的红包置为过期状态
        userRedEnvelopeMapper.changeStatus(new long[]{}, RedStatus.EXPIRED, RedStatus.NO_USE, new Date());
    }

    @Override
    public boolean checkRedEnvelope(long[] redEnvelopeIds, User user) {
        if (redEnvelopeIds == null) {
            return false;
        }
        int count = userRedEnvelopeMapper.checkRedEnvelope(redEnvelopeIds, user.getUserId());
        // 如果查询结果集个数不等于用户所选择的红包ID个数，则代表用户存在恶意修改表单提交ID的嫌疑，所以需要进行处理
        if (count == redEnvelopeIds.length) {
            return true;
        }
        return false;
    }

}

